package com.azzcs.coyote;

import com.azzcs.catalina.Valve;
import com.azzcs.catalina.mapper.Mapper;
import com.azzcs.coyote.endpoint.Endpoint;
import com.azzcs.coyote.endpoint.NioEndpoint;
import com.azzcs.coyote.processor.Http11Processor;
import com.azzcs.coyote.processor.Processor;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;


/**
 * @Author: wzg
 * @Date: 2021/1/7 下午5:52
 */
public class Http11NioProtocol implements ProtocolHandler {

    // 处理 TCP/IP
    private final Endpoint endpoint;

    // 处理 HTTP
    private final Processor processor;

    protected Adapter adapter;

    private Executor executor;

    private int port = 8080;

    private Mapper mapper;

    public Http11NioProtocol() {
        this.endpoint = new NioEndpoint();
        this.processor = new Http11Processor();
    }

    @Override
    public void init() {

    }

    public Adapter getAdapter() {
        return adapter;
    }

    public void setAdapter(Adapter adapter) {
        this.adapter = adapter;
    }

    @Override
    public Executor getExecutor() {
        return executor;
    }

    public void setExecutor(Executor executor) {
        this.executor = executor;
    }

    @Override
    public void start() {
        try {
            ServerSocket serverSocket = new ServerSocket(port);
            while (true) {
                Socket socket = serverSocket.accept();
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        InputStream inputStream = null;
                        try {
                            inputStream = socket.getInputStream();
                            Request request = new Request(inputStream);
                            Response response = new Response();
                            Mapper.MappedHost host = mapper.getHost(request.getHost());
                            Valve hostValue = host.obj.getPipeline().getBasic();
                            hostValue.invoke(request,response);

                            Mapper.MappedContext context = mapper.getContext(host, request.getContext());
                            Valve contextValue = context.obj.getPipeline().getBasic();
                            contextValue.invoke(request,response);

                            Mapper.MappedWrapper wrapper = mapper.getWrapper(context, request.getWrapper());
                            Valve wrapperValue = wrapper.obj.getPipeline().getBasic();
                            wrapperValue.invoke(request,response);

                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void serMapper(Mapper mapper) {
        this.mapper = mapper;
    }
}
